using Circus.CodeEditor;
using Circus.Syntax.Lexer;
using System;
using System.ComponentModel;
using System.Drawing;
namespace Circus.Syntax
{
	[DesignerCategory("Code"), ToolboxItem(true), ToolboxBitmap(typeof(XmlParser), "Images.XmlParser.bmp")]
	public class XmlParser : SyntaxParser
	{
		internal const string CDATA = "![CDATA[";
		protected const int stateNormal = 0;
		protected const int stateTag = 1;
		protected const int stateParam = 2;
		protected const int stateComment = 3;
		protected const int stateCDATA = 4;
		protected const int stateString = 5;
		protected LexerProc lexWhitespaceProc;
		protected LexerProc lexSymbolProc;
		protected LexerProc lexTagProc;
		protected LexerProc lexEqualProc;
		protected LexerProc lexStringProc;
		protected LexerProc lexNameProc;
		protected LexerProc lexBodyProc;
		protected LexerProc lexParamProc;
		protected LexerProc lexStringParamProc;
		protected LexerProc lexParamNumberProc;
		protected LexerProc lexCommentProc;
		protected LexerProc lexCommentEndProc;
		protected LexerProc lexCDATAProc;
		protected LexerProc lexCDATAEndProc;
		protected LexerProc lexStringEndProc;
		protected Point prevPosition;
		public override bool CaseSensitive
		{
			get
			{
				return true;
			}
		}
		protected override void InitLanguage()
		{
			this.Scheme.FileType = "xml";
		}
		protected override void InitStyles()
		{
			this.InitDefaultStyles();
		}
		protected override void InitLexer()
		{
			base.InitLexer();
			this.lexWhitespaceProc = new LexerProc(this.LexWhitespace);
			this.lexSymbolProc = new LexerProc(this.LexSymbol);
			this.lexTagProc = new LexerProc(this.LexTag);
			this.lexEqualProc = new LexerProc(this.LexEqual);
			this.lexStringProc = new LexerProc(this.LexString);
			this.lexNameProc = new LexerProc(this.LexName);
			this.lexBodyProc = new LexerProc(this.LexBody);
			this.lexStringParamProc = new LexerProc(this.LexStringParam);
			this.lexParamProc = new LexerProc(this.LexParam);
			this.lexParamNumberProc = new LexerProc(this.LexParamNumber);
			this.lexCommentProc = new LexerProc(this.LexComment);
			this.lexCommentEndProc = new LexerProc(this.LexCommentEnd);
			this.lexCDATAProc = new LexerProc(this.LexCDATA);
			this.lexCDATAEndProc = new LexerProc(this.LexCDATAEnd);
			this.lexStringEndProc = new LexerProc(this.LexStringEnd);
			base.RegisterLexerProc(0, this.lexBodyProc);
			base.RegisterLexerProc(0, '<', this.lexTagProc);
			base.RegisterLexerProc(1, this.lexWhitespaceProc);
			base.RegisterLexerProc(1, '!', 'ÿ', this.lexSymbolProc);
			base.RegisterLexerProc(1, new char[]
			{
				'/',
				'>',
				'<'
			}, this.lexTagProc);
			base.RegisterLexerProc(1, '=', this.lexEqualProc);
			base.RegisterLexerProc(1, new char[]
			{
				'"',
				'\''
			}, this.lexStringProc);
			base.RegisterLexerProc(1, 'a', 'z', this.lexNameProc);
			base.RegisterLexerProc(1, 'A', 'Z', this.lexNameProc);
			base.RegisterLexerProc(5, this.lexStringEndProc);
			base.RegisterLexerProc(2, this.lexWhitespaceProc);
			base.RegisterLexerProc(2, new char[]
			{
				'/',
				'>'
			}, this.lexTagProc);
			base.RegisterLexerProc(2, new char[]
			{
				'"',
				'\''
			}, this.lexStringParamProc);
			base.RegisterLexerProc(2, 'A', 'Z', this.lexParamProc);
			base.RegisterLexerProc(2, 'a', 'z', this.lexParamProc);
			base.RegisterLexerProc(2, '0', '9', this.lexParamNumberProc);
			base.RegisterLexerProc(3, this.lexCommentEndProc);
			base.RegisterLexerProc(4, ']', this.lexCDATAEndProc);
			base.RegisterLexerProc(4, this.lexCDATAProc);
		}
		protected override int GetLexerStyle(int token)
		{
			int result;
			switch (token)
			{
			case 2:
			case 14:
				result = 5;
				return result;
			case 3:
			case 4:
			case 5:
			case 6:
			case 7:
			case 13:
				result = 7;
				return result;
			case 8:
				result = 7;
				return result;
			case 9:
				result = 9;
				return result;
			case 10:
				result = 2;
				return result;
			case 11:
				result = 3;
				return result;
			}
			result = 6;
			return result;
		}
		protected virtual int LexComment()
		{
			bool flag = this.currentPos > 0 && this.source[this.currentPos - 1] == '<';
			this.currentPos++;
			int result;
			if (flag && this.currentPos < this.source.Length - 1 && this.source[this.currentPos] == '-' && this.source[this.currentPos + 1] == '-')
			{
				this.currentPos += 2;
				this.State = 3;
				result = 11;
			}
			else
			{
				result = 1;
			}
			return result;
		}
		protected virtual int LexCommentEnd()
		{
			int length = this.source.Length;
			if (this.currentPos >= length)
			{
				this.currentPos++;
			}
			else
			{
				while (this.currentPos < length)
				{
					if (this.currentPos < length - 2 && this.source[this.currentPos] == '-' && this.source[this.currentPos + 1] == '-' && this.source[this.currentPos + 2] == '>')
					{
						this.currentPos += 3;
						this.State = 0;
						break;
					}
					this.currentPos++;
				}
			}
			return 11;
		}
		protected virtual int LexCDATAEnd()
		{
			int length = this.source.Length;
			int result;
			if (this.currentPos < length - 2 && this.source[this.currentPos] == ']' && this.source[this.currentPos + 1] == ']' && this.source[this.currentPos + 2] == '>')
			{
				this.currentPos += 3;
				this.State = 0;
				result = 13;
			}
			else
			{
				result = this.LexCDATA();
			}
			return result;
		}
		protected virtual int LexCDATA()
		{
			int length = this.source.Length;
			int result;
			if (this.currentPos >= length)
			{
				this.currentPos++;
			}
			else
			{
				while (this.currentPos < length)
				{
					if (this.currentPos < length - 2 && this.source[this.currentPos] == ']' && this.source[this.currentPos + 1] == ']' && this.source[this.currentPos + 2] == '>')
					{
						result = 14;
						return result;
					}
					this.currentPos++;
				}
			}
			result = 14;
			return result;
		}
		protected virtual int LexWhitespace()
		{
			this.LexSpace();
			return 1;
		}
		protected virtual int LexSymbol()
		{
			XmlLexerToken result = XmlLexerToken.WhiteSpace;
			char c = this.source[this.currentPos];
			this.currentPos++;
			char c2 = c;
			if (c2 == '?')
			{
				result = XmlLexerToken.Interr;
			}
			return (int)result;
		}
		protected virtual int LexBody()
		{
			this.currentPos++;
			int length = this.source.Length;
			while (this.currentPos < length && this.source[this.currentPos] != '<')
			{
				this.currentPos++;
			}
			return 2;
		}
		protected virtual int LexTag()
		{
			char c = this.source[this.currentPos];
			int length = this.source.Length;
			this.currentPos++;
			int result;
			if (c == '<')
			{
				this.State = 1;
				if (this.currentPos < length)
				{
					c = this.source[this.currentPos];
					if (c == '/')
					{
						this.currentPos++;
						result = 5;
					}
					else
					{
						if (c == '!')
						{
							string text = this.source.Substring(this.currentPos);
							if (text.StartsWith("![CDATA["))
							{
								this.State = 4;
								this.currentPos += "![CDATA[".Length;
								result = 13;
								return result;
							}
						}
						if (c == '!' && this.currentPos < length - 2 && this.source[this.currentPos + 1] == '-' && this.source[this.currentPos + 2] == '-')
						{
							result = this.LexComment();
						}
						else
						{
							result = 3;
						}
					}
				}
				else
				{
					result = 3;
				}
			}
			else
			{
				if (c == '>')
				{
					this.State = 0;
					result = 4;
				}
				else
				{
					if (c == '/')
					{
						if (this.currentPos < length)
						{
							c = this.source[this.currentPos];
							if (c == '>')
							{
								this.currentPos++;
								this.State = 0;
								result = 6;
								return result;
							}
						}
					}
					result = 0;
				}
			}
			return result;
		}
		protected virtual int LexEqual()
		{
			this.currentPos++;
			this.State = 2;
			return 7;
		}
		protected virtual int LexString()
		{
			int length = this.source.Length;
			char endChar = this.source[this.currentPos];
			this.currentPos++;
			return this.LexStringEnd(endChar);
		}
		protected virtual int LexStringEnd()
		{
			return this.LexStringEnd('"');
		}
		protected virtual int LexStringEnd(char endChar)
		{
			int length = this.source.Length;
			int result;
			while (this.currentPos < length)
			{
				char c = this.source[this.currentPos];
				if (c == endChar)
				{
					this.currentPos++;
					if (this.currentPos >= length || endChar != '"' || this.source[this.currentPos] != '"')
					{
						this.State = 1;
						result = 10;
						return result;
					}
					this.currentPos++;
				}
				else
				{
					this.currentPos++;
				}
			}
			if (endChar == '"')
			{
				this.State = 5;
			}
			result = 10;
			return result;
		}
		protected virtual int LexStringParam()
		{
			int num = this.LexString();
			return 10;
		}
		protected virtual int LexParam()
		{
			this.LexIdent();
			this.State = 1;
			return 10;
		}
		protected virtual int LexParamNumber()
		{
			this.LexNum();
			this.State = 1;
			return 10;
		}
		protected override void LexIdent()
		{
			this.currentPos++;
			int length = this.source.Length;
			while (this.currentPos < length)
			{
				char c = this.source[this.currentPos];
				if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') && c != '_' && c != ':' && c != '-')
				{
					break;
				}
				this.currentPos++;
			}
		}
		protected virtual int LexName()
		{
			int result = ((this.currentPos > 0 && this.source[this.currentPos - 1] == '<') || (this.currentPos > 1 && this.source[this.currentPos - 1] == '/' && this.source[this.currentPos - 2] == '<')) ? 8 : 9;
			this.LexIdent();
			return result;
		}
		public override void ReparseText()
		{
			this.Reset();
			this.MoveNext();
			this.ParseUnit();
			base.ReparseText();
		}
		public override void ResetOptions()
		{
			this.Options = (SyntaxOptions.Outline | SyntaxOptions.SmartIndent);
		}
		public override CodeCompletionType GetCompletionType(char ch)
		{
			CodeCompletionType result;
			if (ch != '<')
			{
				result = base.GetCompletionType(ch);
			}
			else
			{
				result = CodeCompletionType.ListMembers;
			}
			return result;
		}
		protected virtual bool IsComment(int tok)
		{
			return tok == 11;
		}
		protected override bool IsValidToken(int tok)
		{
			return tok != 0 && tok != 1 && !this.IsComment(tok) && tok != 13 && tok != 14;
		}
		protected virtual bool ParseComment()
		{
			int lineIndex = this.lineIndex;
			SyntaxNode syntaxNode = new SyntaxNode(this.TokenPosition, string.Empty, 8, SyntaxNodeOptions.None);
			this.AddNode(syntaxNode);
			Point currentPosition = this.CurrentPosition;
			while (this.IsComment(this.Token))
			{
				currentPosition = this.CurrentPosition;
				this.NextToken();
			}
			if (this.lineIndex != lineIndex)
			{
				syntaxNode.Options |= SyntaxNodeOptions.Outlining;
			}
			syntaxNode.Range.EndPoint = currentPosition;
			return true;
		}
		protected virtual int MoveNext()
		{
			this.prevPosition = this.CurrentPosition;
			int num = this.NextToken();
			while (!this.Eof && !this.IsValidToken(num))
			{
				if (this.IsComment(this.Token))
				{
					this.ParseComment();
					num = this.Token;
				}
				else
				{
					num = this.NextToken();
				}
			}
			return num;
		}
		protected virtual void AddNode(SyntaxNode node)
		{
			this.SyntaxTree.Current.AddChild(node);
		}
		protected virtual void ReportXmlError(SyntaxNode node, SyntaxError err)
		{
			node.AddError(err);
		}
		protected virtual void SkipTagBody()
		{
			while (!this.Eof)
			{
				if (this.Token == 4)
				{
					break;
				}
				this.MoveNext();
			}
			this.MoveNext();
		}
		protected virtual bool ParseTagBody()
		{
			bool flag = true;
			SyntaxNode current = this.SyntaxTree.Current;
			bool flag2 = this.TokenString == "!" || this.TokenString == "?";
			bool result;
			while (!this.Eof)
			{
				switch (this.Token)
				{
				case 4:
					current.AddAttribute(new SyntaxAttribute(this.TokenPosition, XmlLexerToken.CloseTag.ToString(), null));
					this.MoveNext();
					if (!flag2)
					{
						if (!this.ParseBody())
						{
							flag = false;
						}
					}
					result = flag;
					return result;
				case 5:
				case 7:
					goto IL_118;
				case 6:
					current.AddAttribute(new SyntaxAttribute(this.TokenPosition, XmlLexerToken.CloseEndTag.ToString(), null));
					this.MoveNext();
					result = flag;
					return result;
				case 8:
					if (current.Name == string.Empty)
					{
						current.Name = this.TokenString;
					}
					this.MoveNext();
					break;
				case 9:
					if (!this.ParseParams())
					{
						flag = false;
					}
					break;
				default:
					goto IL_118;
				}
				continue;
				IL_118:
				this.MoveNext();
			}
			result = flag;
			return result;
		}
		protected virtual bool ParseTag(SyntaxNode node)
		{
			bool result = true;
			this.MoveNext();
			bool flag = this.TokenString == "?";
			this.SyntaxTree.Push(node);
			try
			{
				if (!this.ParseTagBody())
				{
					result = false;
				}
			}
			finally
			{
				this.SyntaxTree.Pop();
			}
			node.Range.EndPoint = this.prevPosition;
			if (!flag && node.Range.EndPoint.Y != node.Range.StartPoint.Y)
			{
				node.Options = (SyntaxNodeOptions.Indentation | SyntaxNodeOptions.Outlining);
				node.AddAttribute(new SyntaxAttribute(this.prevPosition, SyntaxConsts.DefinitionScopeEnd, null));
			}
			return result;
		}
		protected virtual bool ParseOpenTag()
		{
			SyntaxNode node = new SyntaxNode(this.TokenPosition, string.Empty, 2);
			this.AddNode(node);
			return this.ParseTag(node);
		}
		protected virtual bool ParseBody()
		{
			bool flag = true;
			SyntaxNode current = this.SyntaxTree.Current;
			bool result;
			while (!this.Eof)
			{
				switch (this.Token)
				{
				case 3:
					if (!this.ParseOpenTag())
					{
						flag = false;
					}
					break;
				case 4:
					goto IL_14F;
				case 5:
				{
					SyntaxNode syntaxNode = new SyntaxNode(this.TokenPosition, string.Empty, 3, SyntaxNodeOptions.None);
					Point tokenPosition = this.TokenPosition;
					this.SaveState();
					try
					{
						this.MoveNext();
						if (this.Token == 8 && string.Compare(current.Name, this.TokenString, !this.CaseSensitive) == 0)
						{
							current.AddChild(syntaxNode);
						}
					}
					finally
					{
						this.RestoreState(string.Compare(this.TokenString, current.Name, !this.CaseSensitive) != 0);
					}
					if (string.Compare(this.TokenString, current.Name, !this.CaseSensitive) != 0)
					{
						this.ReportXmlError(current, new SyntaxError(this.TokenPosition, current.Name, string.Format("{0} end tag {1}", current.Name, StringConsts.ErrExpected)));
						result = flag;
					}
					else
					{
						this.SkipTagBody();
						syntaxNode.Range.EndPoint = this.prevPosition;
						result = flag;
					}
					return result;
				}
				default:
					goto IL_14F;
				}
				continue;
				IL_14F:
				this.AddNode(new SyntaxNode(this.TokenPosition, this.TokenString, 6));
				this.MoveNext();
			}
			result = flag;
			return result;
		}
		protected virtual bool ParseParams()
		{
			string text = string.Empty;
			Point position = Point.Empty;
			SyntaxNode syntaxNode = new SyntaxNode(this.TokenPosition, string.Empty, 5);
			this.SyntaxTree.Push(syntaxNode);
			try
			{
				bool flag = false;
				while (!this.Eof && !flag)
				{
					switch (this.Token)
					{
					case 4:
					case 6:
						flag = true;
						break;
					case 5:
					case 8:
						goto IL_101;
					case 7:
						this.MoveNext();
						break;
					case 9:
						position = this.TokenPosition;
						text = this.TokenString;
						this.MoveNext();
						break;
					case 10:
						if (text != string.Empty)
						{
							SyntaxNode syntaxNode2 = new SyntaxNode(position, text, 4);
							syntaxNode2.AddAttribute(new SyntaxAttribute(this.TokenPosition, XmlNodeType.XmlParameter.ToString(), this.TokenString));
							syntaxNode2.Range.EndPoint = this.CurrentPosition;
							syntaxNode.AddChild(syntaxNode2);
						}
						text = string.Empty;
						this.MoveNext();
						break;
					default:
						goto IL_101;
					}
					continue;
					IL_101:
					this.MoveNext();
				}
			}
			finally
			{
				this.SyntaxTree.Pop();
			}
			syntaxNode.Range.EndPoint = this.prevPosition;
			if (syntaxNode.HasChildren)
			{
				this.SyntaxTree.Current.AddChild(syntaxNode);
			}
			return text == string.Empty;
		}
		protected virtual bool ParseUnit()
		{
			SyntaxNode syntaxNode = this.SyntaxTree.Root;
			syntaxNode.NodeType = 1;
			syntaxNode.Position = Point.Empty;
			bool result = this.ParseBody();
			this.SyntaxTree.Root.Range.EndPoint = this.prevPosition;
			syntaxNode = this.SyntaxTree.Current;
			while (syntaxNode != this.SyntaxTree.Root)
			{
				this.ReportXmlError(syntaxNode, new SyntaxError(syntaxNode.Position, syntaxNode.Name, StringConsts.ErrEndOfFileFound));
				syntaxNode.Range.EndPoint = this.prevPosition;
				this.SyntaxTree.Pop();
				syntaxNode = this.SyntaxTree.Current;
				result = false;
			}
			return result;
		}
		protected override int GetSmartIndent(SyntaxNodes nodes, int index, bool autoIndent)
		{
			int num = base.GetSmartIndent(nodes, index, autoIndent);
			if (autoIndent && num > 0)
			{
				num--;
			}
			return num;
		}
		public override bool GetMultiLineComment(out string start, out string end)
		{
			start = "<!--";
			end = "-->";
			return true;
		}
	}
}
